package com.zhuanzhuan.hero.user.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhuanzhuan.hero.user.config.ThreadPoolConfiguration;
import com.zhuanzhuan.hero.user.enums.RecentDataEnum;
import com.zhuanzhuan.hero.user.recent.assembler.base.RecentMsgAssembleContext;
import com.zhuanzhuan.hero.user.recent.assembler.base.UserRecentMsgAssembler;
import com.zhuanzhuan.hero.user.service.HeroUserLabelAuthRecordService;
import com.zhuanzhuan.hero.user.service.IRecentUpdatesService;
import com.zhuanzhuan.hero.user.util.AsyncUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName RecentUpdatesServiceImpl
 * @Description
 * @Author hanjunjun
 * @Date 2024/7/8 17:10
 */
@Service
@Slf4j
public class RecentUpdatesServiceImpl implements IRecentUpdatesService {
    //近期动态组装超时时间
    public static final int RECENT_MSG_ASSEMBLE_TIMEOUT = 1000;
    @Resource
    private List<UserRecentMsgAssembler> assemblers;
    @Resource
    private HeroUserLabelAuthRecordService userLabelAuthRecordService;

    @Override
    public List<String> queryUserRecentUpdates(Long uid) {
        if(uid == null){
            return Lists.newArrayList();
        }
        Map<Long, List<String>> map = batchQueryUserRecentUpdates(Lists.newArrayList(uid));
        if(MapUtils.isEmpty(map)){
            return Lists.newArrayList();
        }
        return map.values().iterator().next();
    }

    @Override
    public Map<Long, List<String>> batchQueryUserRecentUpdates(List<Long> uidList) {
        RecentMsgAssembleContext context = new RecentMsgAssembleContext();
        context.setUids(uidList);
        List<CompletableFuture<Map<Long, EnumMap<RecentDataEnum, String>>>> futures = Lists.newArrayList();
        for (UserRecentMsgAssembler assembler : assemblers) {
            CompletableFuture<Map<Long,EnumMap<RecentDataEnum, String>>> future =
                AsyncUtil.call(() -> assembler.assemble(context), ThreadPoolConfiguration.USER_RECENT_EXECUTOR);
            futures.add(future);
        }
        Map<Long,EnumMap<RecentDataEnum, String>> recentMsgMap = Maps.newHashMap();
        futures.forEach(f ->{
            try {
                Map<Long, EnumMap<RecentDataEnum, String>> resultMap = AsyncUtil.result(f, RECENT_MSG_ASSEMBLE_TIMEOUT,
                    TimeUnit.MILLISECONDS);
                if(MapUtils.isEmpty(resultMap)){
                    return;
                }
                resultMap.forEach((uid, recentMsg) -> {
                    recentMsgMap.compute(uid, (k, v) ->{
                        v = v == null ? new EnumMap<>(RecentDataEnum.class) : v;
                        v.putAll(recentMsg);
                        return v;
                    });
                });
            } catch (Exception e) {
                log.error("recent msg assemble err, context:{}", context, e);
            }
        });
        Map<Long, List<String>> result = Maps.newHashMap();
        //需要按照固定顺序返回，以枚举的顺序为准
        recentMsgMap.forEach((uid, map) -> {
            List<String> msgList = Arrays.stream(RecentDataEnum.values()).map(recentType -> {
                String recentMsg = map.get(recentType);
                if (StringUtils.isNotBlank(recentMsg)) {
                    return recentMsg;
                }
                return Strings.EMPTY;
            }).filter(StringUtils::isNotBlank).collect(Collectors.toList());
            result.put(uid, msgList);
        });
        return result;
    }
}
